package com.project.frba.bi.transformation;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import com.project.frba.bi.descriptor.Dimension;
import com.project.frba.bi.descriptor.Property;
import com.project.frba.bi.extraction.ExtractionResult;

public class DimensionTable implements Table {
	
	private Dimension dimension; 
	private Long index = 1L;
	private Map<Long, Row> dimensionRows = new HashMap<Long, Row>();
	
	public DimensionTable(Dimension dimension) {
		this.dimension = dimension;
	}
	
	public String getDimensionName(){
		return this.dimension.getName();
	}
	
	public Class getColumnType(String columnName){
		return this.dimension.getPropertyType(columnName);
	}
	
	public Integer getDimensionId(DimensionRow row){
		if(this.dimensionRows.containsKey(row.hashCode())){
			this.dimensionRows.get(row.hashCode()).getId();
		}
		return 0;
	}
	
	public DimensionRow getDimensionById(Long id){
		return (DimensionRow)this.dimensionRows.get(id);
	}
	
	public String getTableName(){
		return this.dimension.getName();
	}
	
	public Integer getRowCount(){
		return this.dimensionRows.size();
	}
	
	public Collection<String> getColumns(){
		return this.dimension.getPropertyNames();
	}
	
	public String getInsertStatement(){
		StringBuffer insertStatement = new StringBuffer();
		insertStatement.append("INSERT INTO " + dimension.getDescriptor().getDescriptorName() + dimension.getName() + "dimension");
		insertStatement.append("(");
		insertStatement.append("id");
		for(Property property : this.getDimension().getProperties()){
			insertStatement.append("," + property.getName());	
		}
		insertStatement.append(") VALUES ");
		
		for (Row row : this.dimensionRows.values()) {
			insertStatement.append(row.getInsertValueStatement() + ",");
		}
		
		return insertStatement.substring(0, insertStatement.lastIndexOf(",")) + ";";
		
	}

	public void addRow(Row dimensionRow) {
		if(this.dimensionRows.containsValue(dimensionRow)){
			//TODO refactor to improve performance
			for(Row row: this.dimensionRows.values()){
				if(row.equals(dimensionRow)){
					dimensionRow.setId(row.getId());
				}
			}
		} else {
			dimensionRow.setId(this.getActualIndex());
			this.dimensionRows.put(dimensionRow.getId(), dimensionRow);
			this.incrementIndex();
		}
	}
	
	private void incrementIndex(){
		this.index++;
	}
	
	public Long getActualIndex(){
		return this.index;
	}

	public Long process(ExtractionResult result) {
		DimensionRow dimensionRow = new DimensionRow(this);
		for(String columnName: this.getColumns()){
			dimensionRow.addColumnValue(columnName, result.getValue(columnName, this.getColumnType(columnName)));
		}
		addRow(dimensionRow);
		return dimensionRow.getId();
	}

	public Dimension getDimension() {
		return this.dimension;
	}

	@Override
	public String getInsertStatement(Long startIndex, Long endIndex) {
		// TODO Auto-generated method stub
		return null;
	}


}
